package framework.security.password;

import lombok.Getter;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * 密码模式默认处理类
 */
public class PasswordServiceDefault implements PasswordService {

    @Getter
    private final Map<String, PasswordMode> encodeMap = new HashMap<>();

    @Getter
    private String defaultMode;

    public PasswordServiceDefault() {
        PasswordMD5Mode mode = new PasswordMD5Mode();
        this.addMode(mode);
        //
        this.defaultMode = mode.getName();
    }

    /**
     * 设置默认密码模式
     *
     * @param mode
     */
    public void setDefaultMode(String mode) {
        if (!this.encodeMap.containsKey(mode)) {
            throw new RuntimeException("Not set password mode: " + mode);
        }
        this.defaultMode = mode;
    }

    /**
     * 密码集合
     *
     * @return
     */
    @Override
    public Collection<PasswordMode> modes() {
        return this.encodeMap.values();
    }

    /**
     * 密码编码
     *
     * @param password
     * @param salt
     * @return
     */
    public String encode(String password, String salt) {
        String mode = this.defaultMode;
        String en = this.getMode(mode).encode(password, salt);
        return mode + "," + en;
    }

    /**
     * 密码编码
     *
     * @param password
     * @param salt
     * @param mode
     * @return
     */
    public String encode(String mode, String password, String salt) {
        String en = this.getMode(mode).encode(password, salt);
        return mode + "," + en;
    }

    /**
     * 校验密码是否匹配
     *
     * @param salt
     * @param password
     * @param encodePassword
     * @return
     */
    @Override
    public boolean matched(String password, String salt, String encodePassword) {
        String[] items = encodePassword.split(",");
        if (items.length != 2) return false;
        String mode = items[0];
        encodePassword = items[1];
        //String mode,
        boolean matched = this.getMode(mode).matched(password, salt, encodePassword);
        return matched;
    }

    /**
     * 依据模式返回密码编码器
     *
     * @param name
     * @return
     */
    public PasswordMode getMode(String name) {
        PasswordMode passwordMode = this.encodeMap.get(name);
        if (passwordMode == null)
            throw new RuntimeException("Not support PasswordMode: " + name);
        return passwordMode;
    }

    /**
     * 添加密码模式
     *
     * @param mode
     */
    @Override
    public void addMode(PasswordMode mode) {
        synchronized (encodeMap) {
            this.encodeMap.put(mode.getName(), mode);
        }
    }

    /**
     * 添加密码模式
     *
     * @param mode
     */
    public void delMode(PasswordMode mode) {
        synchronized (encodeMap) {
            this.encodeMap.remove(mode.getName());
        }
    }

    /**
     * 删除密码模式
     *
     * @param name
     */
    @Override
    public void delMode(String name) {
        synchronized (encodeMap) {
            this.encodeMap.remove(name);
        }
    }
}
